/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package info.kimjihyok.voiceripple;

import info.kimjihyok.ripplelibrary.ColorPicker;
import info.kimjihyok.ripplelibrary.util.Constant;
import info.kimjihyok.ripplelibrary.renderer.Renderer;
import info.kimjihyok.ripplelibrary.renderer.TimerCircleRippleRenderer;
import info.kimjihyok.ripplelibrary.VoiceRippleView;
import info.kimjihyok.ripplelibrary.listener.RecordingListener;
import info.kimjihyok.ripplelibrary.util.Rate;
import info.kimjihyok.ripplelibrary.util.ResUtil;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentState;
import ohos.agp.components.Image;
import ohos.agp.components.RadioButton;
import ohos.agp.components.Slider;
import ohos.agp.components.element.StateElement;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.security.SystemPermission;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import static ohos.bundle.IBundleManager.PERMISSION_GRANTED;

/**
 * 功能主入口
 *
 * @since 2021-04-29
 */
public class MainAbility extends Ability implements RecordingListener {
    private static final int EVENT_MESSAGE_NORMAL = 1;
    private Slider ripplesize;
    private Slider iconsize;
    private VoiceRippleView voiceRipple;
    private final List<String> mPermissions =
            new LinkedList<>(
                    Collections.singletonList(SystemPermission.MICROPHONE));
    private RadioButton low;
    private RadioButton medium;
    private RadioButton high;
    private RadioButton samplelow;
    private RadioButton samplemedium;
    private RadioButton samplehigh;
    private Image videoimage;
    private UpdateHandler updateHandler;
    /**
     * 衰减率
     *
     * @noinspection checkstyle:DeclarationOrder
     */
    private final Component.ClickedListener optionOnClickListener = new RadioButton.ClickedListener() {
        @Override
        public void onClick(Component component) {
            if (low.isChecked()) {
                voiceRipple.setRippleDecayRate(Rate.LOW);
            } else if (medium.isChecked()) {
                voiceRipple.setRippleDecayRate(Rate.MEDIUM);
            } else if (high.isChecked()) {
                voiceRipple.setRippleDecayRate(Rate.HIGH);
            }
        }
    };

    // 采样率
    private final Component.ClickedListener sampleOnClickListener = new RadioButton.ClickedListener() {
        @Override
        public void onClick(Component component) {
            if (samplelow.isChecked()) {
                voiceRipple.setRippleSampleRate(Rate.LOW);
            } else if (samplemedium.isChecked()) {
                voiceRipple.setRippleSampleRate(Rate.MEDIUM);
            } else if (samplehigh.isChecked()) {
                voiceRipple.setRippleSampleRate(Rate.HIGH);
            }
        }
    };

    /**
     * onStart
     *
     * @param intent intent
     */
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        ripplesize = (Slider) findComponentById(ResourceTable.Id_ripplesize);
        iconsize = (Slider) findComponentById(ResourceTable.Id_iconsize);
        videoimage = (Image) findComponentById(ResourceTable.Id_videoimage);
        low = (RadioButton) findComponentById(ResourceTable.Id_decayradio_low);
        medium = (RadioButton) findComponentById(ResourceTable.Id_decayradio_med);
        high = (RadioButton) findComponentById(ResourceTable.Id_decayradio_hight);

        samplelow = (RadioButton) findComponentById(ResourceTable.Id_sampleradio_low);
        samplemedium = (RadioButton) findComponentById(ResourceTable.Id_sampleradio_med);
        samplehigh = (RadioButton) findComponentById(ResourceTable.Id_sampleradio_high);

        voiceRipple = (VoiceRippleView) findComponentById(ResourceTable.Id_voiceRipple);
        voiceRipple.setClickedListener(component -> reqPermissions());

        // 录音波纹设置： 采样率，衰减率，波纹比
        voiceRipple.setRippleSampleRate(Rate.LOW); // 采样率
        voiceRipple.setRippleDecayRate(Rate.HIGH); // 衰减率
        voiceRipple.setBackgroundRippleRatio(Constant.NUMBER1_4); // 波纹比
        ColorPicker colorpicker = (ColorPicker) findComponentById(ResourceTable.Id_colorpicker);
        colorpicker.setOnColorChangedListener(color -> voiceRipple.setRippleColor(color));
        Button playervideo = (Button) findComponentById(ResourceTable.Id_playervideo);
        updateState();

        playervideo.setClickedListener(component -> {
            if (!voiceRipple.isRecording()) {
                voiceRipple.playReset();
                startPlay();
            }
        });

        setListener();
    }

    /**
     * 事件监听
     */
    public void setListener() {
        ripplesize.setValueChangedListener(new Slider.ValueChangedListener() {
            @Override
            public void onProgressUpdated(Slider slider, int ii, boolean isBoot) {
                if (ii == 0 || ii == Constant.NUMBER100) {
                    return;
                }
                double ratio = Constant.ZOREFIVEF + ((double) ii / Constant.NUMBER100F);
                voiceRipple.setBackgroundRippleRatio(ratio);
            }

            @Override
            public void onTouchStart(Slider slider) {
            }

            @Override
            public void onTouchEnd(Slider slider) {
            }
        });

        iconsize.setValueChangedListener(new Slider.ValueChangedListener() {
            @Override
            public void onProgressUpdated(Slider slider, int ii, boolean isBoot) {
                int value = ii / Constant.NUMBER10;
                InnerEvent normalInnerEvent = InnerEvent.get(EVENT_MESSAGE_NORMAL, value, null);
                updateHandler.sendEvent(normalInnerEvent, 0, EventHandler.Priority.LOW);
            }

            @Override
            public void onTouchStart(Slider slider) {
            }

            @Override
            public void onTouchEnd(Slider slider) {
            }
        });

        // 设置衰减率
        low.setButtonElement(setSelect());
        medium.setButtonElement(setSelect());
        high.setButtonElement(setSelect());

        low.setClickedListener(optionOnClickListener);
        medium.setClickedListener(optionOnClickListener);
        high.setClickedListener(optionOnClickListener);
        high.setChecked(true);

        // 设置采样率
        samplelow.setButtonElement(setSelect());
        samplemedium.setButtonElement(setSelect());
        samplehigh.setButtonElement(setSelect());

        samplelow.setClickedListener(sampleOnClickListener);
        samplemedium.setClickedListener(sampleOnClickListener);
        samplehigh.setClickedListener(sampleOnClickListener);
        samplelow.setChecked(true);

        EventRunner runner = EventRunner.current();
        updateHandler = new UpdateHandler(runner);
    }

    /**
     * 单选图片选择
     *
     * @return 单选图片选择
     */
    public StateElement setSelect() {
        StateElement stateElement = new StateElement();
        stateElement.addState(new int[]{ComponentState.COMPONENT_STATE_CHECKED},
                ResUtil.getPixelMapDrawable(getContext(), ResourceTable.Media_radioselect));
        stateElement.addState(new int[]{ComponentState.COMPONENT_STATE_EMPTY},
                ResUtil.getPixelMapDrawable(getContext(), ResourceTable.Media_radionormal));

        return stateElement;
    }

    private void reqPermissions() {
        mPermissions.removeIf(perM -> verifySelfPermission(perM) == PERMISSION_GRANTED || !canRequestPermission(perM));
        if (!mPermissions.isEmpty()) {
            requestPermissionsFromUser(
                    mPermissions.toArray(new String[0]), Constant.NUMBER1003);
        } else {
            inVideo();
        }
    }

    /**
     * onRequestPermissionsFromUserResult
     *
     * @param requestCode requestCode
     * @param permissions permissions
     * @param grantResults grantResults
     */
    @Override
    public void onRequestPermissionsFromUserResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsFromUserResult(requestCode, permissions, grantResults);
        if (requestCode != 0) {
            inVideo();
            return;
        }
        boolean isHavePermission = false;
        for (int num = 0; num < permissions.length; num++) {
            isHavePermission = grantResults[num] == PERMISSION_GRANTED;
        }
        if (isHavePermission) {
            restart();
        }
    }

    /**
     * 视频开始和暂停点击
     */
    public void inVideo() {
        voiceRipple.setRecordingListener(this);
        if (voiceRipple.isRecording()) {
            voiceRipple.stopRecording();
            videoimage.setPixelMap(ResourceTable.Media_record);
        } else {
            voiceRipple.startRecording();
            videoimage.setPixelMap(ResourceTable.Media_recording);
        }
    }

    /**
     * 更新圆环初始化进度
     */
    public void updateState() {
        Renderer currentRenderer = new TimerCircleRippleRenderer(getDefaultRipplePaint(),
                getDefaultRippleBackgroundPaint(),
                getButtonPaint(), getArcPaint(), Constant.NUMBER10000F, 0.0);
        ((TimerCircleRippleRenderer) currentRenderer).setStrokeWidth(Constant.NUMBER20);
        voiceRipple.setRenderer(currentRenderer);
    }

    /**
     * 播放音频
     */
    private void startPlay() {
        voiceRipple.filePlay();
    }

    private Paint getArcPaint() {
        Paint paint = new Paint();
        paint.setColor(new Color(Color.rgb(Constant.NUMBER72, Constant.NUMBER36, Constant.NUMBER41)));
        paint.setStrokeWidth(Constant.NUMBER20);
        paint.setAntiAlias(true);
        paint.setStrokeCap(Paint.StrokeCap.SQUARE_CAP);
        paint.setStyle(Paint.Style.STROKE_STYLE);
        return paint;
    }

    private Paint getDefaultRipplePaint() {
        Paint ripplePaint = new Paint();
        ripplePaint.setStyle(Paint.Style.FILL_STYLE);
        ripplePaint.setColor(new Color((Color.rgb(Constant.NUMBER255, Constant.NUMBER204, 0)
                & Constant.COLOR00FFFFFF) | Constant.COLOR40000000));
        ripplePaint.setAntiAlias(true);

        return ripplePaint;
    }

    private Paint getDefaultRippleBackgroundPaint() {
        Paint rippleBackgroundPaint = new Paint();
        rippleBackgroundPaint.setStyle(Paint.Style.FILL_STYLE);
        rippleBackgroundPaint.setColor(new Color((Color.rgb(Constant.NUMBER255, Constant.NUMBER204, 0)
                & Constant.COLOR00FFFFFF) | Constant.COLOR40000000));
        rippleBackgroundPaint.setAntiAlias(true);

        return rippleBackgroundPaint;
    }

    private Paint getButtonPaint() {
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.WHITE);
        paint.setStyle(Paint.Style.FILL_STYLE);
        return paint;
    }

    /**
     * onRecordingStopped
     */
    @Override
    public void onRecordingStopped() {
        videoimage.setPixelMap(ResourceTable.Media_record);
    }

    /**
     * onRecordingStarted
     */
    @Override
    public void onRecordingStarted() {
    }

    /**
     * 更新UI类
     *
     * @since 2021-04-29
     */
    final class UpdateHandler extends EventHandler {
        private UpdateHandler(EventRunner runner) {
            super(runner);
        }

        // 重写实现processEvent方法
        @Override
        public void processEvent(InnerEvent event) {
            super.processEvent(event);
            if (event == null) {
                return;
            }
            int eventId = event.eventId;
            if (eventId == EVENT_MESSAGE_NORMAL) {
                int width = (int) event.param;
                if (width <= Constant.NUMBER6) {
                    videoimage.setScaleX((float) width);
                    videoimage.setScaleY((float) width);
                } else {
                    videoimage.setScaleX((float) Constant.NUMBER6 + (float)width / Constant.NUMBER10);
                    videoimage.setScaleY((float) Constant.NUMBER6 + (float)width / Constant.NUMBER10);
                }
                updateHandler.removeEvent(eventId);
            }
        }
    }
}